<template>
  <div class="app-container">
    <!-- 搜索表单 -->
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
      <el-form-item label="存储类型" prop="storageType">
        <el-select v-model="queryParams.storageType" placeholder="请选择存储类型" clearable>
          <el-option label="全部" value="" />
          <el-option v-for="dict in options.sys_file_storage_type" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
        </el-select>
      </el-form-item>
      <el-form-item label="文件可见性" prop="visibility">
        <el-select v-model="queryParams.visibility" placeholder="请选择可见性" clearable >
          <el-option v-for="dict in options.sys_file_visibility" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
        </el-select>
      </el-form-item>
      <el-form-item label="文件状态" prop="status">
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
          <el-option v-for="dict in options.sys_file_status" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
        </el-select>
      </el-form-item>
      <el-form-item label="文件ID" prop="fileId">
        <el-input v-model="queryParams.fileId" placeholder="请输入文件ID" @keyup.enter="handleQuery" clearable />
      </el-form-item>
      <el-form-item label="文件名称" prop="realName">
        <el-input v-model="queryParams.realName" placeholder="请输入文件原名" @keyup.enter="handleQuery" clearable />
      </el-form-item>
      <el-form-item label="创建时间">
        <el-date-picker
          v-model="dateRange"
          type="daterange"
          range-separator="-"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          @change="handleDateChange"
          value-format="YYYY-MM-DD HH:mm:ss">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="debouncedHandleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <!-- 操作按钮 -->
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" plain icon="Upload" @click="handleAdd" v-hasPermi="['tool:file:add']"> 上传 </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['tool:file:edit']"> 编辑 </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['tool:file:remove']"> 删除 </el-button>
      </el-col>
      <el-col :span="2">
        <el-button type="info" plain icon="Download" @click="handleBatchDownload" :disabled="!ids.length || multiple"> 批量下载 </el-button>
      </el-col>
    
      <el-col :span="2" style="text-align: right">
        <el-tag :type="currentUserType === '1' ? 'warning' : currentUserType === '2' ? 'success' : 'info'">
          {{ currentUserType === '1' ? '系统用户' : currentUserType === '2' ? '个人用户' : currentUserType === '3' ? '团队用户' : '未知用户' }}
        </el-tag>
      </el-col>
      <right-toolbar :showSearch="showSearch" @queryTable="handleQuery"></right-toolbar>
    </el-row>

    <!-- 文件表格 -->
    <el-table
      :data="fileList"
      v-loading="loading"
      border
      @selection-change="handleSelectionChange"
      @sort-change="handleSortChange"
      height="calc(100vh - 320px)" >
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="文件ID" align="center" prop="id" width="120" sortable />
      <el-table-column label="文件名称" :show-overflow-tooltip="true">
        <template #default="scope">
          <el-link type="primary" @click="showFileDetail(scope.row)">
            {{ scope.row.realName }}
          </el-link>
        </template>
      </el-table-column>
      <el-table-column label="预览图" align="center" width="80">
        <template #default="{ row }">
          <el-image
            :src="row.accessUrl + '?thumbnail=80x80'"
            fit="contain"
            lazy
            class="el-avatar"
            v-if="row.fileType?.includes('image')"
            :preview-src-list="[row.accessUrl]">
            <template #error>
              <el-icon><Document /></el-icon>
            </template>
          </el-image>
          <el-icon v-else><Document /></el-icon>
        </template>
      </el-table-column>
      <el-table-column label="文件大小" align="center" prop="fileSize">
        <template #default="scope">
          {{ formatFileSize(scope.row.fileSize) }}
        </template>
      </el-table-column>
      <el-table-column label="存储类型" align="center" prop="storageType">
        <template #default="scope">
          <dict-tag :options="options.sys_file_storage_type" :value="scope.row.storageType" />
        </template>
      </el-table-column>
      <el-table-column label="可见性" align="center" prop="visibility">
        <template #default="scope">
          <dict-tag :options="options.sys_file_visibility" :value="scope.row.visibility"  />
        </template>
      </el-table-column>
      <el-table-column label="文件状态" align="center" prop="status">
        <template #default="scope">
          <dict-tag :options="options.sys_file_status" :value="scope.row.status" />
        </template>
      </el-table-column>
      <el-table-column label="下载次数" align="center" prop="downloadCount" sortable />
      <el-table-column label="最近操作" align="center" prop="updateTime" width="180" sortable />
      <el-table-column label="操作" align="center">
        <template #default="scope">
          <el-button text size="small" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['tool:file:edit']"> 编辑 </el-button>
          <el-button
            text
            size="small"
            icon="Download"
            @click="handleDownload(scope.row)"
            :disabled="scope.row.status === '2'"
            :title="scope.row.status === '2' ? '文件已禁用，无法下载' : ''">
            下载
          </el-button>
          <el-button text size="small" icon="Copy" @click="copyText(scope.row.accessUrl)"> 复制 </el-button>
          <el-button
            text
            size="small"
            icon="Delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['tool:file:remove']"
            :disabled="scope.row.status === '2'">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页组件 -->
    <pagination
      v-show="total > 0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
      :page-sizes="[10, 20, 50, 100]" />

    <!-- 新增/修改对话框（小文件上传） -->
    <el-dialog :title="title" v-model="open" draggable width="780px" append-to-body>
      <el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
        <el-form-item label="文件信息" prop="file">
          <!-- 编辑模式：显示已上传文件 -->
          <div v-if="form.id" class="file-info-container">
            <div class="file-info-header">
              <el-icon v-if="form.fileType?.includes('image')" class="file-icon"><Picture /></el-icon>
              <el-icon v-else-if="form.fileType?.includes('pdf')" class="file-icon"><Document /></el-icon>
              <el-icon v-else-if="form.fileType?.includes('video')" class="file-icon"><Video /></el-icon>
              <el-icon v-else class="file-icon"><File /></el-icon>

              <div class="file-name">{{ form.realName }}</div>

              <el-button text size="small" @click="handleReupload" class="reupload-btn"> 重新上传 </el-button>
            </div>

            <div class="file-meta">
              <div class="meta-item">
                <span class="meta-label">文件大小：</span>
                <span>{{ formatFileSize(form.fileSize) }}</span>
              </div>
              <div class="meta-item">
                <span class="meta-label">存储路径：</span>
                <span :title="form.storagePath">{{ form.storagePath }}</span>
              </div>
              <div class="meta-item">
                <span class="meta-label">文件类型：</span>
                <span>{{ form.fileType || '未知' }}</span>
              </div>
              <div class="meta-item" v-if="form.fileHash">
                <span class="meta-label">文件哈希：</span>
                <span :title="form.fileHash">{{ form.fileHash.substring(0, 10) }}...</span>
              </div>
            </div>
          </div>

          <!-- 新增模式：显示上传按钮 -->
          <el-upload
            v-else
            class="upload-demo"
            ref="smallFileUploadRef"
            :auto-upload="false"
            :on-change="handleSmallFileChange"
            :file-list="smallFileList"
            :limit="1"
            accept=".jpg,.jpeg,.png,.pdf,.doc,.docx,.xls,.xlsx">
            <el-button type="primary" icon="Upload">选择小文件</el-button>
            <template #tip>
              <div class="el-upload__tip text-muted">支持上传5MB以下文件，格式：jpg、png、pdf、doc、xls等</div>
            </template>
          </el-upload>
        </el-form-item>

        <el-row :gutter="20">
          <!-- 文件名类型选择 -->
          <el-col :lg="12">
            <el-form-item label="文件名类型" prop="fileNameType">
              <el-select v-model="form.fileNameType" placeholder="请选择文件名类型" style="width:100%">
                <el-option label="原文件名" :value="1" />
                <el-option label="自定义名" :value="2" />
                <el-option label="哈希名" :value="3" />
              </el-select>
            </el-form-item>
          </el-col>
          
          <!-- 自定义文件名（仅当选择自定义名时显示） -->
          <el-col :lg="12" v-if="form.fileNameType === 2">
            <el-form-item label="自定义文件名" prop="fileName">
              <el-input v-model="form.fileName" placeholder="请输入自定义文件名" />
            </el-form-item>
          </el-col>

          <el-col :lg="12">
            <el-form-item label="文件原名" prop="realName">
              <el-input v-model="form.realName" placeholder="请输入文件原名（含扩展名）" @blur="autoFillFileExt" disabled v-if="smallFileList.length" />
              <el-input v-model="form.realName" placeholder="请输入文件原名（含扩展名）" @blur="autoFillFileExt" v-else />
              <div class="el-form-item__help">选择文件后自动填充，不可修改</div>
            </el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="存储类型" prop="storageType">
              <el-select v-model="form.storageType" placeholder="请选择存储类型" style="width:100%">
                <el-option v-for="dict in options.sys_file_storage_type" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
              </el-select>
            </el-form-item>
          </el-col>
          
          <!-- 存储目录前缀 -->
          <el-col :lg="12">
            <el-form-item label="存储目录前缀" prop="fileDir">
              <el-input v-model="form.fileDir" placeholder="请输入存储目录前缀（如：/uploads）" />
            </el-form-item>
          </el-col>
          
          <!-- 存储路径标识 -->
          <el-col :lg="12">
            <el-form-item label="存储路径标识" prop="storagePath">
              <el-input v-model="form.storagePath" type="number" placeholder="请输入存储路径标识" />
            </el-form-item>
          </el-col>

          <el-col :lg="12">
            <el-form-item label="可见性" prop="visibility">
              <el-select v-model="form.visibility" placeholder="请选择可见性" @change="handleVisibilityChange" style="width:100%">
                <el-option v-for="dict in options.sys_file_visibility" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
              </el-select>
            </el-form-item>
          </el-col>
          
          <!-- 图片压缩质量 -->
          <el-col :lg="12">
            <el-form-item label="压缩质量" prop="quality">
              <el-slider
                v-model="form.quality"
                :min="1"
                :max="100"
                :step="1"
                :show-input="true"
                :input-size="'small'"
                :tooltip="false">
              </el-slider>
              <div class="el-form-item__help">1表示最低压缩，100表示最高质量，值越大文件质量越高</div>
            </el-form-item>
          </el-col>

          <el-col :lg="12">
            <el-form-item label="文件状态" prop="status">
              <el-select v-model="form.status" placeholder="请选择文件状态" style="width:100%">
                <el-option label="定时删除" value="0" />
                <el-option label="正常" value="1" />
                <el-option label="禁用" value="2" />
              </el-select>
            </el-form-item>
          </el-col>

          <!-- 动态子配置项（根据可见性显示） -->
          <el-col :lg="24" v-if="form.visibility === '1'">
            <el-divider content-position="left">免费配置</el-divider>
            <el-row :gutter="20">
              <el-col :lg="12">
                <el-form-item label="下载次数限制" prop="fileFree.downloadLimit">
                  <el-input
                    v-model="form.fileFree.downloadLimit"
                    type="number"
                    placeholder="0表示无限制"
                    min="0"
                    :suffix="form.fileFree.downloadLimit === 0 ? '无限制' : '次'" />
                </el-form-item>
              </el-col>
              <el-col :lg="12">
                <el-form-item label="免费有效期">
                  <el-date-picker v-model="form.fileFree.expireAt" type="datetime" placeholder="请选择有效期" style="width:100%" />
                </el-form-item>
              </el-col>
            </el-row>
          </el-col>

          <el-col :lg="24" v-if="form.visibility === '2'">
            <el-divider content-position="left">付费配置</el-divider>
            <el-row :gutter="20">
              <el-col :lg="12">
                <el-form-item label="单次下载价格" prop="filePayPerDownload.price">
                  <el-input v-model="form.filePayPerDownload.price" type="number" placeholder="请输入单价（元）" min="0" step="0.01" prefix="¥" />
                </el-form-item>
              </el-col>
              <el-col :lg="12">
                <el-form-item label="折扣率" prop="filePayPerDownload.discount">
                  <el-input
                    v-model="form.filePayPerDownload.discount"
                    type="number"
                    placeholder="请输入折扣率（如1.00）"
                    min="0.01"
                    max="1"
                    step="0.01"
                    suffix="%"
                    @input="handleDiscountChange" />
                </el-form-item>
              </el-col>
            </el-row>
          </el-col>

          <el-col :lg="24" v-if="form.visibility === '3'">
            <el-divider content-position="left">会员配置</el-divider>
            <el-row :gutter="20">
              <el-col :lg="12">
                <el-form-item label="所需会员等级" prop="fileMember.requiredMemberLevel">
                  <el-select v-model="form.fileMember.requiredMemberLevel" placeholder="请选择会员等级">
                    <el-option v-for="level in options.sys_member_level" :key="level.value" :label="level.label" :value="level.value" />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :lg="12">
                <el-form-item label="免费下载次数" prop="fileMember.freeDownloadCount">
                  <el-input v-model="form.fileMember.freeDownloadCount" type="number" placeholder="请输入免费下载次数" min="0" suffix="次" />
                </el-form-item>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button text @click="cancel">取消</el-button>
        <el-button type="primary" @click="submitForm" :loading="formLoading" :disabled="(!smallFileList.length && !form.id) || formLoading">
          提交
        </el-button>
      </template>
    </el-dialog>

    <!-- 查看详情对话框 -->
    <el-dialog :title="`文件详情 - ID: ${formDetail.id || ''}`" v-model="detailVisible" draggable width="800px" append-to-body>
      <el-form :model="formDetail" label-width="120px" label-position="left">
        <el-row :gutter="20">
          <el-col :lg="12">
            <el-form-item label="文件ID">{{ formDetail.id }}</el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="文件原名">{{ formDetail.realName }}</el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="存储文件名">{{ formDetail.name }}</el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="文件类型">{{ formDetail.fileType }}</el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="扩展名">{{ formDetail.fileExt }}</el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="文件大小">{{ formatFileSize(formDetail.fileSize) }}</el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="文件哈希">
              <el-tooltip effect="dark" content="点击复制文件哈希" placement="top">
                <span class="hash-text" @click="copyText(formDetail.fileHash)">{{ formDetail.fileHash }}</span>
              </el-tooltip>
            </el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="下载次数">{{ formDetail.downloadCount || 0 }} 次</el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="存储类型">
              <dict-tag :options="options.sys_file_storage_type" :value="formDetail.storageType" />
            </el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="可见性">
              <dict-tag :options="options.sys_file_visibility" :value="formDetail.visibility" />
            </el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="文件状态">
              <dict-tag :options="options.sys_file_status" :value="formDetail.status" />
            </el-form-item>
          </el-col>
          <el-col :lg="12">
            <el-form-item label="创建时间">{{ formDetail.createTime }}</el-form-item>
          </el-col>

          <!-- 子配置详情 -->
          <el-col :lg="24" v-if="formDetail.visibility === '1' && formDetail.fileFree">
            <el-divider content-position="left">免费配置详情</el-divider>
            <el-row :gutter="20">
              <el-col :lg="12">
                <el-form-item label="下载次数限制">{{ formDetail.fileFree.downloadLimit }} 次</el-form-item>
              </el-col>
              <el-col :lg="12">
                <el-form-item label="免费有效期">{{ formDetail.fileFree.expireAt || '永久有效' }}</el-form-item>
              </el-col>
            </el-row>
          </el-col>

          <el-col :lg="24" v-if="formDetail.visibility === '2' && formDetail.filePayPerDownload">
            <el-divider content-position="left">付费配置详情</el-divider>
            <el-row :gutter="20">
              <el-col :lg="10">
                <el-form-item label="单次下载价格">{{ formDetail.filePayPerDownload.price }} 元</el-form-item>
              </el-col>
              <el-col :lg="10">
                <el-form-item label="折扣率">{{ (formDetail.filePayPerDownload.discount * 100).toFixed(0) }}%</el-form-item>
              </el-col>
              <el-col :lg="4">
                <el-form-item label="销量">{{ formDetail.filePayPerDownload.salesCount }} 次</el-form-item>
              </el-col>
            </el-row>
          </el-col>

          <el-col :lg="24" v-if="formDetail.visibility === '3' && formDetail.fileMember">
            <el-divider content-position="left">会员配置详情</el-divider>
            <el-row :gutter="20">
              <el-col :lg="12">
                <el-form-item label="所需会员等级">
                  <span>{{ getDictLabel(options.sys_member_level, formDetail.fileMember.requiredMemberLevel) }}</span>
                </el-form-item>
              </el-col>
              <el-col :lg="12">
                <el-form-item label="会员免费下载次数">{{ formDetail.fileMember.freeDownloadCount }} 次</el-form-item>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button text @click="detailVisible = false">关闭</el-button>
      </template>
    </el-dialog>

    <!-- 收费文件支付弹窗 -->
    <el-dialog :title="'文件付费下载'" v-model="payVisible" draggable width="400px" append-to-body>
      <el-form :model="payForm" label-width="100px">
        <el-form-item label="文件名称">
          <span>{{ payForm.fileName }}</span>
        </el-form-item>
        <el-form-item label="原价">
          <span>¥{{ payForm.originalPrice }}</span>
        </el-form-item>
        <el-form-item label="折扣价">
          <span>¥{{ payForm.discountPrice }}</span>
        </el-form-item>
        <el-form-item label="支付方式">
          <el-radio-group v-model="payForm.payType">
            <el-radio-button label="1">微信支付</el-radio-button>
            <el-radio-button label="2">支付宝支付</el-radio-button>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button text @click="payVisible = false">取消</el-button>
        <el-button type="primary" @click="submitPay" :loading="payLoading">确认支付</el-button>
      </template>
    </el-dialog>

    <!-- 大文件/文件夹分片上传弹窗 -->
    <el-dialog :title="multipartForm.id ? '编辑大文件' : '大文件/文件夹分片上传'" v-model="multipartVisible" draggable width="600px" append-to-body>
      <el-form ref="multipartFormRef" :model="multipartForm" :rules="multipartRules" label-width="100px" class="multipart-form">
        <!-- 文件/文件夹选择区域 -->
        <el-form-item label="文件/文件夹信息" prop="files" required>
          <!-- 编辑模式：显示已上传文件信息 -->
          <div v-if="multipartForm.id" class="file-info-container">
            <div class="file-info-header">
              <el-icon v-if="multipartForm.fileType?.includes('image')" class="file-icon"><Picture /></el-icon>
              <el-icon v-else-if="multipartForm.fileType?.includes('folder')" class="file-icon"><Folder /></el-icon>
              <el-icon v-else class="file-icon"><File /></el-icon>

              <div class="file-name">{{ multipartForm.fileName }}</div>

              <el-button text size="small" @click="handleReuploadLargeFile" class="reupload-btn"> 重新上传 </el-button>
            </div>

            <div class="file-meta">
              <div class="meta-item">
                <span class="meta-label">文件大小：</span>
                <span>{{ formatFileSize(multipartForm.fileSize) }}</span>
              </div>
              <div class="meta-item">
                <span class="meta-label">存储路径：</span>
                <span :title="multipartForm.storagePath">{{ multipartForm.storagePath }}</span>
              </div>
              <div class="meta-item">
                <span class="meta-label">上传时间：</span>
                <span>{{ multipartForm.uploadTime }}</span>
              </div>
            </div>
          </div>

          <!-- 新增模式：显示上传按钮 -->
          <el-upload
            v-else
            ref="multipartUploadRef"
            :auto-upload="false"
            :on-change="handleFileChange"
            :before-change="beforeFileChange"
            :on-remove="handleFileRemove"
            class="upload-demo"
            action="#"
            :file-list="multipartFileList"
            :accept="acceptFileTypes"
            :directory="multipartForm.uploadType === 'folder'"
            multiple>
            <el-button type="primary" icon="Upload">
              {{ multipartForm.uploadType === 'folder' ? '选择文件夹' : '选择大文件' }}
            </el-button>
            <template #tip>
              <div class="el-upload__tip text-muted">
                <template v-if="multipartForm.uploadType === 'folder'"> 支持上传整个文件夹（内含文件不超过200个，单个文件不超过1GB） </template>
                <template v-else> 支持大文件分片上传，最大支持1GB单个文件 </template>
                <br />支持格式：{{ acceptFileTypesText }}
              </div>
            </template>
          </el-upload>
        </el-form-item>

        <!-- 上传类型切换 -->
        <el-form-item label="上传类型" prop="uploadType" v-if="!multipartForm.id">
          <el-radio-group v-model="multipartForm.uploadType" @change="handleUploadTypeChange">
            <el-radio-button label="file">单个大文件</el-radio-button>
            <el-radio-button label="folder">整个文件夹</el-radio-button>
          </el-radio-group>
        </el-form-item>

        <!-- 存储路径 -->
        <el-form-item label="存储根路径" prop="storagePath" :required="multipartForm.uploadType === 'folder' || !multipartForm.id">
          <el-input
            v-model="multipartForm.storagePath"
            placeholder="请输入存储根路径（如：/uploads/projectA）"
            :disabled="!multipartForm.uploadType && !multipartForm.id" />
          <div class="el-form-item__help">文件夹上传时，所有文件会保存在该路径下；文件上传时为可选</div>
        </el-form-item>

        <!-- 基础配置 -->
        <el-form-item label="存储类型" prop="storageType" required>
          <el-select v-model="multipartForm.storageType" placeholder="请选择存储类型">
            <el-option v-for="dict in options.sys_file_storage_type" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
          </el-select>
        </el-form-item>

        <el-form-item label="可见性" prop="visibility" required>
          <el-select v-model="multipartForm.visibility" placeholder="请选择可见性" style="width:100%">
            <el-option v-for="dict in options.sys_file_visibility" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
          </el-select>
        </el-form-item>

        <!-- 高级配置 -->
        <el-collapse v-model="activeAdvancedConfig" v-if="!multipartForm.id">
          <el-collapse-item title="高级配置">
            <el-form-item label="分片大小">
              <el-select v-model="multipartForm.chunkSize" placeholder="选择分片大小">
                <el-option label="2MB" value="2" />
                <el-option label="5MB" value="5" />
                <el-option label="10MB" value="10" />
              </el-select>
            </el-form-item>
            <el-form-item label="并发数">
              <el-select v-model="multipartForm.concurrent" placeholder="选择并发上传数">
                <el-option label="1" value="1" />
                <el-option label="2" value="2" />
                <el-option label="3" value="3" />
              </el-select>
            </el-form-item>
          </el-collapse-item>
        </el-collapse>

        <!-- 上传进度 -->
        <el-progress :percentage="uploadProgress" v-if="uploadProgress > 0 && uploadProgress < 100" stroke-width="6">
          <template #format="scope">
            {{ scope.percentage.toFixed(0) }}%
            <span v-if="multipartForm.uploadType === 'file'"> ({{ uploadedChunks }}/{{ chunkCount }} 分片) </span>
            <span v-else> ({{ uploadedFiles }}/{{ totalFiles }} 文件) </span>
          </template>
        </el-progress>

        <!-- 上传控制按钮 -->
        <div v-if="uploadProgress > 0 && uploadProgress < 100" class="upload-controls">
          <el-button text size="small" icon="Pause" @click="toggleUploadStatus" v-if="uploadStatus === 'uploading'"> 暂停上传 </el-button>
          <el-button text size="small" icon="Play" @click="toggleUploadStatus" v-if="uploadStatus === 'paused'"> 继续上传 </el-button>
          <el-button text size="small" icon="Close" @click="cancelUpload" type="danger"> 取消上传 </el-button>
        </div>
      </el-form>
      <template #footer>
        <el-button text @click="cancelUpload">取消</el-button>
        <el-button
          type="primary"
          @click="startMultipartUpload"
          :disabled="(!multipartFileList.length && !multipartForm.id) || uploadProgress > 0 || !isFormValid || formLoading">
          {{ multipartForm.id ? '保存修改' : '开始上传' }}
        </el-button>
      </template>
    </el-dialog>

    <!-- 下载进度弹窗 -->
    <el-dialog :title="'正在下载'" v-model="downloadProgressVisible" draggable width="400px" append-to-body :close-on-click-modal="false">
      <div class="download-progress">
        <el-progress :percentage="downloadProgress" stroke-width="6" />
        <div class="download-info">已下载大小: {{ formatFileSize(downloadedSize) }} / {{ formatFileSize(totalDownloadSize) }}</div>
      </div>
      <template #footer>
        <el-button text @click="cancelDownload">取消</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="fileManage">
import { ref, reactive, toRefs, computed, onMounted, onUnmounted, getCurrentInstance } from 'vue'
import { useClipboard } from '@vueuse/core'
import { ElMessage, ElMessageBox } from 'element-plus'
import store from '@/store'
import request from '@/utils/request'
import {
  listFile,
  getFile,
  addFile,
  updateFile,
  delFile,
  checkFileAccess,
  initMultipartUpload,
  uploadPart,
  completeMultipartUpload,
  batchDownloadFile
} from '@/api/tool/file'
import useUserStore from '@/store/modules/user'
import { getDicts } from '@/api/system/dict/data'

const { proxy } = getCurrentInstance()
const userInfo = computed(() => useUserStore().userInfo)

// 工具函数
const formatFileSize = (bytes) => {
  if (bytes === 0 || !bytes) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i]
}

const getDictLabel = (options, value) => {
  const option = options.find((item) => item.dictValue === value || item.value === value)
  return option ? option.dictLabel || option.label : ''
}

const getFileTypeByExt = (ext) => {
  const extMap = {
    jpg: 'image/jpeg',
    jpeg: 'image/jpeg',
    png: 'image/png',
    gif: 'image/gif',
    pdf: 'application/pdf',
    doc: 'application/msword',
    docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    xls: 'application/vnd.ms-excel',
    xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    zip: 'application/zip',
    rar: 'application/x-rar-compressed',
    mp4: 'video/mp4',
    txt: 'text/plain'
  }
  return extMap[ext.toLowerCase()] || 'application/octet-stream'
}

const debounce = (fn, delay) => {
  let timer = null
  return function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, args), delay)
  }
}

// 全局状态
const loading = ref(true)
const formLoading = ref(false)
const payLoading = ref(false)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const showSearch = ref(true)
const total = ref(0)
const fileList = ref([])
const title = ref('')
const open = ref(false)
const detailVisible = ref(false)
const payVisible = ref(false)
const multipartVisible = ref(false)
const currentUserType = ref('2')
const currentUserMemberLevel = ref('2')
const dateRange = ref([])
const formRef = ref()
const downloadProgressVisible = ref(false)
const downloadProgress = ref(0)
const downloadedSize = ref(0)
const totalDownloadSize = ref(0)

// 小文件上传状态
const smallFileList = ref([])
const smallFileUploadRef = ref(null)
const currentSmallFile = ref(null)
const showReupload = ref(false)

// 大文件/文件夹上传状态
const multipartFormRef = ref(null)
const multipartUploadRef = ref(null)
const multipartFileList = ref([])
const uploadProgress = ref(0)
const uploadStatus = ref('idle')
const activeAdvancedConfig = ref([])
let uploadId = ''
let chunkCount = 0
let uploadedChunks = 0
let totalFiles = 0
let uploadedFiles = 0
let uploadQueue = []
let currentFileIndex = 0
let abortControllers = []

// 支持的文件类型
const acceptFileTypes = ref('.jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.zip,.rar,.mp4,.txt')
const acceptFileTypesText = computed(() => acceptFileTypes.value.replace(/\./g, '').split(',').join('、'))

// 响应式数据（状态字段统一为字符串）
const state = reactive({
  options: {
    sys_file_storage_type: [],
    sys_file_visibility: [
     ],
    sys_file_status: [
     ],
    sys_member_level: [
    ]
  },
  rules: {
    // 基础必填字段验证
    realName: [{ required: true, message: '文件原名不能为空', trigger: 'blur' }],
    fileExt: [{ required: true, message: '文件扩展名不能为空', trigger: 'blur' }],
    fileType: [{ required: true, message: '文件类型不能为空', trigger: 'blur' }],
    storageType: [{ required: true, message: '存储类型不能为空', trigger: 'change' }],
    visibility: [{ required: true, message: '可见性不能为空', trigger: 'change' }],
    status: [{ required: true, message: '文件状态不能为空', trigger: 'change' }],
    fileNameType: [{ required: true, message: '请选择文件名类型', trigger: 'change' }],
    
    // 子字段验证（根据可见性动态生效）
    'fileFree.downloadLimit': [{ 
      required: (rule) => state.form.visibility === '1', 
      message: '请输入下载次数限制', 
      trigger: 'blur' 
    }],
    'filePayPerDownload.price': [{ 
      required: (rule) => state.form.visibility === '2', 
      message: '请输入单次下载价格', 
      trigger: 'blur' 
    }],
    'fileMember.requiredMemberLevel': [{ 
      required: (rule) => state.form.visibility === '3', 
      message: '请选择所需会员等级', 
      trigger: 'change' 
    }],
    
    // 其他字段验证
    fileName: [{ 
      required: (rule) => state.form.fileNameType === 2, 
      message: '请输入自定义文件名', 
      trigger: 'blur' 
    }],
    quality: [{ type: 'number', min: 1, max: 100, message: '压缩质量必须在1-100之间', trigger: 'change' }]
  },
  form: {
    // 基础字段（状态字段为字符串）
    id: undefined,
    realName: '',
    fileExt: '',
    fileHash: '',
    fileSize: 0,
    fileType: '',
    fileNameType: 3,
    fileName: '',
    fileDir: '',
    storagePath: undefined,
    quality: 100,
    storageType: '',
    visibility: '1', // 默认公开可见
    status: '1', // 默认正常
    accessUrl: '',
    name: '',
    downloadCount: 0,
    
    // 子配置字段
    fileFree: { downloadLimit: 0, expireAt: null },
    filePayPerDownload: { price: 0, discount: 1.0, salesCount: 0 },
    fileMember: { requiredMemberLevel: '1', freeDownloadCount: 0 }
  },
  formDetail: {},
  payForm: {
    fileId: 0,
    fileName: '',
    originalPrice: 0,
    discountPrice: 0,
    payType: '1'
  },
  multipartForm: {
    id: undefined,
    fileName: '',
    fileSize: 0,
    fileType: '',
    uploadTime: '',
    uploadType: 'file',
    storageType: '1',
    visibility: '1',
    storagePath: '/uploads',
    chunkSize: '5',
    concurrent: '2'
  },
  multipartRules: {
    uploadType: [{ required: true, message: '请选择上传类型', trigger: 'change' }],
    storageType: [{ required: true, message: '请选择存储类型', trigger: 'change' }],
    visibility: [{ required: true, message: '请选择可见性', trigger: 'change' }],
    storagePath: [
      {
        required: () => state.multipartForm.uploadType === 'folder' || !state.multipartForm.id,
        message: '文件夹上传必须指定存储根路径',
        trigger: 'blur'
      }
    ],
    files: [{ required: true, message: '请选择文件或文件夹', trigger: 'change' }]
  },
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    storageType: undefined,
    visibility: undefined,
    status: undefined,
    fileId: undefined,
    realName: undefined,
    Sort: undefined,
    SortType: undefined,
    CreateTimeStart: undefined,
    CreateTimeEnd: undefined
  }
})

const { options, rules, form, formDetail, payForm, multipartForm, multipartRules, queryParams } = toRefs(state)

// 大文件表单验证状态
const isFormValid = computed(() => {
  if (!multipartForm.value.storageType || !multipartForm.value.visibility) return false
  if ((multipartForm.value.uploadType === 'folder' || !multipartForm.value.id) && !multipartForm.value.storagePath) return false
  return true
})

// 日期范围处理
const handleDateChange = () => {
  if (dateRange.value && dateRange.value.length === 2) {
    queryParams.value.CreateTimeStart = dateRange.value[0]
    queryParams.value.CreateTimeEnd = dateRange.value[1]
  } else {
    queryParams.value.CreateTimeStart = undefined
    queryParams.value.CreateTimeEnd = undefined
  }
}

// 排序处理
const handleSortChange = (sort) => {
  if (sort.order) {
    queryParams.value.Sort = sort.column.prop
    queryParams.value.SortType = sort.order === 'asc' ? 'ascending' : 'descending'
  } else {
    queryParams.value.Sort = undefined
    queryParams.value.SortType = undefined
  }
  getList()
}

// 获取文件列表
const getList = async () => {
  loading.value = true
  const timeoutId = setTimeout(() => {
    console.error('getList超时，强制关闭loading')
    ElMessage.error('加载超时，请点击"手动刷新"重试')
    loading.value = false
  }, 10000)

  try {
    const response = await listFile(queryParams.value)
    // 核心修改：接口返回的列表是 result，总条数是 totalNum
    fileList.value = response.data.result || []  // 原代码是 response.data.rows
    total.value = response.data.totalNum || 0    // 原代码是 response.data.total
  } catch (error) {
    console.error('listFile失败：', error.message)
    ElMessage.error(error.msg || '获取文件列表失败')
    fileList.value = []
    total.value = 0
  } finally {
    clearTimeout(timeoutId)
    loading.value = false
  }
}

// 取消操作
const cancel = () => {
  open.value = false
  resetForm()
}

// 表单重置
const resetForm = () => {
  form.value = {
    id: undefined,
    realName: '',
    fileExt: '',
    fileHash: '',
    fileSize: 0,
    fileType: '',
    fileNameType: 3,
    fileName: '',
    fileDir: '/uploads',
    storagePath: 0,
    quality: 100,
    storageType: '1',
    visibility: '1',
    status: '1',
    accessUrl: '',
    name: '',
    downloadCount: 0,
    fileFree: { downloadLimit: 0, expireAt: null },
    filePayPerDownload: { price: 0, discount: 1.0, salesCount: 0 },
    fileMember: { requiredMemberLevel: '1', freeDownloadCount: 0 }
  }
  smallFileList.value = []
  currentSmallFile.value = null
  showReupload.value = false
  if (formRef.value) formRef.value.resetFields()
}

// 统一列表加载入口
const debouncedHandleQuery = debounce(handleQuery, 500)
function handleQuery() {
  queryParams.value.pageNum = 1
  getList()
}

// 重置查询
const resetQuery = () => {
  dateRange.value = []
  queryParams.value = {
    pageNum: 1,
    pageSize: 10,
    storageType: undefined,
    visibility: undefined,
    status: undefined,
    fileId: undefined,
    realName: undefined,
    Sort: undefined,
    SortType: undefined,
    CreateTimeStart: undefined,
    CreateTimeEnd: undefined
  }
  if (formRef.value) formRef.value.resetFields()
  handleQuery()
}

// 上传按钮处理
const handleAdd = () => {
  ElMessageBox.confirm('请选择上传方式', '提示', {
    confirmButtonText: '大文件上传',
    cancelButtonText: '小文件上传',
    type: 'info'
  })
    .then(() => {
      multipartVisible.value = true
      multipartFileList.value = []
      uploadProgress.value = 0
      uploadStatus.value = 'idle'
      multipartForm.value = {
        id: undefined,
        fileName: '',
        fileSize: 0,
        fileType: '',
        uploadTime: '',
        uploadType: 'file',
        storageType: '1',
        visibility: '1',
        storagePath: '/uploads',
        chunkSize: '5',
        concurrent: '2'
      }
    })
    .catch(() => {
      resetForm()
      open.value = true
      title.value = '新增文件'
    })
}

// 选中行变化
const handleSelectionChange = (selection) => {
  ids.value = selection.map((item) => item.id)
  single.value = selection.length !== 1
  multiple.value = !selection.length
}

// 修改操作
const handleUpdate = async (row) => {
  resetForm()
  const fileId = row?.id || ids.value[0]
  if (!fileId) return

  try {
    const response = await getFile(fileId)
    const fileData = response.data

    // 补全子配置字段，状态字段转字符串
    form.value = { 
      ...fileData,
      realName: fileData.realName || '',
      fileExt: fileData.fileExt || '',
      fileHash: fileData.fileHash || '',
      fileType: fileData.fileType || '',
      fileNameType: fileData.fileNameType || 3,
      fileName: fileData.fileName || '',
      fileDir: fileData.fileDir || '',
      storagePath: fileData.storagePathId,
      quality: fileData.quality || 100,
      storageType:fileData.StorageType?.toString() || '1',
      visibility: fileData.visibility?.toString() || '1',
      status: fileData.status?.toString() || '1',
      fileFree: fileData.fileFree || { downloadLimit: 0, expireAt: null },
      filePayPerDownload: fileData.filePayPerDownload || { price: 0, discount: 1.0, salesCount: 0 },
      fileMember: fileData.fileMember || { requiredMemberLevel: '1', freeDownloadCount: 0 }
    }
    open.value = true
    title.value = '编辑文件'
  } catch (error) {
    ElMessage.error(error.msg || '获取文件信息失败')
  }
}

// 提交表单主函数
const submitForm = async () => {
  // 先校验表单有效性
  const valid = await new Promise((resolve) => {
    formRef.value.validate((isValid) => resolve(isValid));
  });

  if (!valid) return;

  formLoading.value = true;
  try {
    // 1. 小文件上传（新增场景且有文件时）
    if (!form.value.id && currentSmallFile.value) {
      const formData = new FormData();
      // 核心文件参数
      formData.append('File', currentSmallFile.value); // 后端DTO字段是File，需与后端参数名一致
 console.log('aaaaaaaaaaaaaaaa',currentSmallFile.value)
      // 补全UploadDto所有必填/可选参数（严格对齐后端DTO字段名）
      formData.append('FileNameType', form.value.fileNameType || 3); // 默认哈希名
      formData.append('FileName', form.value.realName || ''); // 自定义文件名
      formData.append('FileDir', form.value.fileDir || ''); // 存储目录
      if (form.value.storagePath !== undefined && form.value.storagePath !== null) {
        formData.append('StoragePath', form.value.storagePath); // 存储路径标识（可选）
      }
      formData.append('Status', form.value.status || 1); // 文件状态（默认正常）
      formData.append('Quality', form.value.quality || 100); // 压缩质量（默认100）
      formData.append('StorageType', form.value.storageType || 1); // 存储类型（默认本地）
      formData.append('Visibility', form.value.visibility || 1); // 可见性（默认公开）

      // 调用后端上传接口
      const uploadResponse = await request({
        url: 'fileapi/File/Upload',
        method: 'post',
        data: formData,
        headers: { 'Content-Type': 'multipart/form-data' },
        // 大文件可加进度条（可选）
        onUploadProgress: (progressEvent) => {
          const progress = (progressEvent.loaded / progressEvent.total) * 100;
          // 可绑定到进度条组件：formProgress.value = progress
        }
      });

      // 解析上传结果（与后端返回字段对齐）
      const { fileId, accessUrl, fileName, storageType, fileHash } = uploadResponse.data;
      // 回写表单数据
      form.value.id = fileId;
      form.value.accessUrl = accessUrl;
      form.value.name = fileName;
      form.value.storageType = storageType;
      form.value.fileSize = currentSmallFile.value.size; // 字节数
      form.value.fileHash = fileHash || '';
    }

    // 2. 校验并补全文件扩展名和类型
    if (!form.value.realName) {
      throw new Error('文件名称不能为空');
    }
    const ext = form.value.realName.split('.').pop();
    if (!ext) {
      throw new Error('文件名称格式错误，无法提取扩展名（需包含后缀，如.png/.pdf）');
    }
    form.value.fileExt = ext.toLowerCase(); // 统一转为小写
    form.value.fileType = getFileTypeByExt(ext);

    // 3. 根据可见性补全子配置（确保字段结构完整）
    switch (form.value.visibility.toString()) {
      case '1': // 公开免费
        form.value.fileFree = form.value.fileFree || { downloadLimit: 0, expireAt: null };
        break;
      case '2': // 按次收费
        form.value.filePayPerDownload = form.value.filePayPerDownload || {
          price: 0,
          discount: 1.0,
          salesCount: 0
        };
        break;
      case '3': // 会员专属
        form.value.fileMember = form.value.fileMember || {
          requiredMemberLevel: '1',
          freeDownloadCount: 0
        };
        break;
      default:
        throw new Error(`不支持的可见性类型：${form.value.visibility}`);
    }

    // 4. 格式化提交数据（确保类型与后端一致）
    const submitData = { ...form.value };
    // 转为字符串类型（后端接收int，前端转字符串不影响，避免类型转换问题）
    submitData.visibility = submitData.visibility.toString();
    submitData.status = submitData.status.toString();
    // 移除不需要提交的临时字段
    delete submitData.realName; // 假设realName仅用于前端显示，后端用FileName

    // 5. 提交新增/修改
    if (form.value.id) {
      await updateFile(submitData);
      ElMessage.success('文件信息修改成功');
    } else {
      if (!form.value.id) throw new Error('文件上传失败，未获取到文件ID');
      await addFile(submitData);
      ElMessage.success('文件新增成功');
    }

    // 操作成功后关闭弹窗并刷新列表
    open.value = false;
    handleQuery();
  } catch (error) {
    // 错误处理：友好提示+重试选项
    ElMessageBox.confirm(
      `操作失败：${error.message || error.msg || '未知错误'}`,
      '操作失败',
      {
        confirmButtonText: '重试',
        cancelButtonText: '取消',
        type: 'error'
      }
    ).then(() => {
      submitForm(); // 重试
    }).catch(() => {
      // 取消重试，重置加载状态
      formLoading.value = false;
    });
  } finally {
    formLoading.value = false;
  }
};

// 删除操作
const handleDelete = async (row) => {
  const fileIds = row?.id ? [row.id] : ids.value
  if (!fileIds.length) return

  try {
    await ElMessageBox.confirm(`确定要删除选中文件"${fileIds.join(',')}"?`, '警告')
    await delFile(fileIds.join(','))
    ElMessage.success('删除成功')
    handleQuery()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error(error.msg || '删除失败')
    }
  }
}

// 查看详情
const showFileDetail = async (row) => {
  try {
    const response = await getFile(row.id)
    formDetail.value = response.data
    detailVisible.value = true
  } catch (error) {
    ElMessage.error(error.msg || '获取文件详情失败')
  }
}

// 可见性变化
const handleVisibilityChange = () => {
  if (form.value.visibility === '1') {
    form.value.fileFree = form.value.fileFree || { downloadLimit: 0, expireAt: null }
  } else if (form.value.visibility === '2') {
    form.value.filePayPerDownload = form.value.filePayPerDownload || { price: 0, discount: 1.0, salesCount: 0 }
  } else if (form.value.visibility === '3') {
    form.value.fileMember = form.value.fileMember || { requiredMemberLevel: '1', freeDownloadCount: 0 }
  }
}

// 折扣处理
const handleDiscountChange = (val) => {
  if (val !== null && val !== undefined) {
    form.value.filePayPerDownload.discount = Math.min(100, Math.max(0, val)) / 100
  }
}

// 提取扩展名
const autoFillFileExt = () => {
  if (!form.value.realName) return
  const ext = form.value.realName.split('.').pop()
  if (ext && ext.length <= 5) {
    form.value.fileExt = ext
    form.value.fileType = getFileTypeByExt(ext)
  }
}

// 下载文件
const handleDownload = async (row) => {
  if (row.status === '2') {
    ElMessage.warning('文件已禁用，无法下载')
    return
  }

  try {
    const accessResponse = await checkFileAccess({
      FileId: row.id,
      UserId: store.getters.userId
    })

    if (!accessResponse.data.hasAccess) {
      if (row.visibility === '2') {
        payForm.value.fileId = row.id
        payForm.value.fileName = row.realName
        payForm.value.originalPrice = row.filePayPerDownload?.price || 0
        payForm.value.discountPrice = (payForm.value.originalPrice * (row.filePayPerDownload?.discount || 1)).toFixed(2)
        payVisible.value = true
      } else {
        ElMessage.warning(accessResponse.data.message || '无下载权限')
      }
      return
    }

    startDownload(row.id, row.fileSize)
  } catch (error) {
    ElMessage.error(error.msg || '下载失败')
  }
}

// 批量下载
const handleBatchDownload = async () => {
  if (!ids.value.length) return
  try {
    const response = await batchDownloadFile(ids.value)
    const { fileUrl, totalSize } = response.data
    totalDownloadSize.value = totalSize
    downloadProgressVisible.value = true
    downloadProgress.value = 0
    downloadedSize.value = 0

    const interval = setInterval(() => {
      downloadedSize.value += totalSize / 10
      downloadProgress.value = Math.min(100, (downloadedSize.value / totalSize) * 100)
      if (downloadProgress.value >= 100) {
        clearInterval(interval)
        setTimeout(() => {
          downloadProgressVisible.value = false
          window.open(fileUrl, '_blank')
        }, 500)
      }
    }, 500)
  } catch (error) {
    ElMessage.error(error.msg || '批量下载失败')
  }
}

// 开始下载
const startDownload = (fileId, fileSize) => {
  totalDownloadSize.value = fileSize
  downloadProgressVisible.value = true
  downloadProgress.value = 0
  downloadedSize.value = 0

  const downloadWindow = window.open(`/fileapi/File/Download?fileId=${fileId}`, '_blank')

  const interval = setInterval(() => {
    downloadedSize.value += fileSize / 10
    downloadProgress.value = Math.min(100, (downloadedSize.value / fileSize) * 100)
    if (downloadProgress.value >= 100 || !downloadWindow || downloadWindow.closed) {
      clearInterval(interval)
      downloadProgressVisible.value = false
    }
  }, 500)
}

// 取消下载
const cancelDownload = () => {
  downloadProgressVisible.value = false
  downloadProgress.value = 0
  downloadedSize.value = 0
  totalDownloadSize.value = 0
}

// 复制文本
const { copy, isSupported } = useClipboard()
const copyText = async (val) => {
  if (!val) return
  if (isSupported) {
    await copy(val)
    ElMessage.success('复制成功')
  } else {
    ElMessage.error('复制失败')
  }
}

// 提交支付
const submitPay = () => {
  payLoading.value = true
  setTimeout(() => {
    ElMessage.success('支付成功')
    payVisible.value = false
    payLoading.value = false
    startDownload(payForm.value.fileId, 0)
  }, 1500)
}

// 小文件选择处理
const handleSmallFileChange = (file) => {
  smallFileList.value = [file]
  currentSmallFile.value = file.raw
  
  // 自动填充必填字段
  form.value.realName = file.name || ''
  const ext = file.name?.split('.').pop()
  if (ext) {
    form.value.fileExt = ext
    form.value.fileType = getFileTypeByExt(ext)
  } else {
    form.value.fileExt = ''
    form.value.fileType = ''
  }
}

// 重新上传小文件
const handleReupload = () => {
  smallFileList.value = []
  currentSmallFile.value = null
  showReupload.value = true
  setTimeout(() => {
    showReupload.value = false
  }, 0)
}

// 重新上传大文件
const handleReuploadLargeFile = () => {
  multipartFileList.value = []
  uploadQueue = []
  multipartForm.value.fileName = ''
  multipartForm.value.fileSize = 0
  multipartForm.value.fileType = ''
  multipartForm.value.uploadTime = ''
}

// 大文件上传类型切换
const handleUploadTypeChange = (type) => {
  multipartFileList.value = []
  uploadQueue = []
  if (type === 'folder') {
    multipartForm.value.concurrent = '1'
  } else {
    multipartForm.value.concurrent = '2'
  }
}

// 大文件选择处理
const handleFileChange = (uploadFile, fileList) => {
  multipartFileList.value = fileList
  uploadQueue = fileList.map((item) => item.raw)
  totalFiles = fileList.length
  if (fileList.length === 1 && multipartForm.value.uploadType === 'file') {
    multipartForm.value.fileName = fileList[0].name
    const ext = fileList[0].name?.split('.').pop()
    if (ext) {
      multipartForm.value.fileType = getFileTypeByExt(ext)
    }
  }
}

// 大文件移除处理
const handleFileRemove = (file, fileList) => {
  multipartFileList.value = fileList
  uploadQueue = fileList.map((item) => item.raw)
  totalFiles = fileList.length
}

// 大文件选择前校验
const beforeFileChange = (file) => {
  const maxSize = 1024 * 1024 * 1024
  if (file.size > maxSize) {
    ElMessage.error(`文件过大：${file.name}，最大支持1GB`)
    return false
  }
  if (multipartForm.value.uploadType === 'folder' && fileList.length > 200) {
    ElMessage.error('文件夹内文件过多，最多支持200个文件')
    return false
  }
  return true
}

// 开始大文件上传
const startMultipartUpload = async () => {
  if (multipartForm.value.id) {
    formLoading.value = true
    try {
      await updateFile({
        id: multipartForm.value.id,
        storageType: multipartForm.value.storageType,
        visibility: multipartForm.value.visibility,
        storagePath: multipartForm.value.storagePath
      })
      ElMessage.success('修改成功')
      multipartVisible.value = false
      handleQuery()
    } catch (error) {
      ElMessageBox.confirm(`操作失败: ${error.msg || '未知错误'}，是否重试？`, '操作失败', {
        confirmButtonText: '重试',
        cancelButtonText: '取消',
        type: 'error'
      }).then(() => {
        startMultipartUpload()
      })
    } finally {
      formLoading.value = false
    }
    return
  }

  try {
    const valid = await multipartFormRef.value.validate()
    if (!valid) return

    uploadProgress.value = 0
    uploadStatus.value = 'uploading'
    uploadedFiles = 0
    currentFileIndex = 0

    if (multipartForm.value.uploadType === 'folder') {
      await uploadNextFileInFolder()
    } else {
      const currentFile = uploadQueue[0]
      await handleSingleFileUpload(currentFile)
    }
  } catch (err) {
    if (uploadStatus.value !== 'cancelled') {
      ElMessageBox.confirm(`上传失败: ${err.msg || '未知错误'}，是否重试？`, '上传失败', {
        confirmButtonText: '重试',
        cancelButtonText: '取消',
        type: 'error'
      })
        .then(() => {
          uploadProgress.value = 0
          startMultipartUpload()
        })
        .catch(() => {
          uploadStatus.value = 'idle'
          formLoading.value = false
        })
    }
  }
}

// 文件夹上传下一个文件
const uploadNextFileInFolder = async () => {
  if (currentFileIndex >= uploadQueue.length || uploadStatus.value !== 'uploading') {
    if (currentFileIndex >= uploadQueue.length) {
      ElMessage.success(`文件夹上传完成，共${totalFiles}个文件`)
      multipartVisible.value = false
      uploadStatus.value = 'idle'
      uploadProgress.value = 0
      handleQuery()
    }
    return
  }

  const currentFile = uploadQueue[currentFileIndex]
  await handleSingleFileUpload(currentFile)

  currentFileIndex++
  uploadedFiles++
  uploadProgress.value = Math.floor((uploadedFiles / totalFiles) * 100)
  await uploadNextFileInFolder()
}

// 处理单个大文件上传
const handleSingleFileUpload = async (file) => {
  return new Promise(async (resolve, reject) => {
    try {
      const initResponse = await initMultipartUpload({
        FileName: file.name,
        FileSize: file.size,
        StorageType: multipartForm.value.storageType,
        StoragePath: getFileStoragePath(file)
      })
      uploadId = initResponse.data.UploadId
      const { ChunkCount, ChunkSize } = initResponse.data
      chunkCount = ChunkCount
      uploadedChunks = 0

      const chunks = []
      const chunkSizeBytes = ChunkSize * 1024 * 1024
      for (let i = 0; i < ChunkCount; i++) {
        const start = i * chunkSizeBytes
        const end = Math.min((i + 1) * chunkSizeBytes, file.size)
        chunks.push({ index: i, start, end })
      }

      const concurrent = parseInt(multipartForm.value.concurrent)
      await uploadChunksInBatches(file, chunks, concurrent)

      await completeMultipartUpload({
        UploadId: uploadId,
        Visibility: multipartForm.value.visibility,
        StorageType: multipartForm.value.storageType
      })
      resolve()
    } catch (err) {
      reject(err)
    }
  })
}

// 批量上传分片
const uploadChunksInBatches = async (file, chunks, batchSize) => {
  if (chunks.length === 0 || uploadStatus.value !== 'uploading') return

  const batch = chunks.splice(0, batchSize)
  const promises = batch.map((chunk) => uploadSingleChunk(file, chunk))
  await Promise.all(promises)
  await uploadChunksInBatches(file, chunks, batchSize)
}

// 上传单个分片
const uploadSingleChunk = async (file, chunk) => {
  return new Promise((resolve, reject) => {
    if (uploadStatus.value !== 'uploading') {
      resolve()
      return
    }

    const { index, start, end } = chunk
    const chunkBlob = file.slice(start, end)
    const formData = new FormData()
    formData.append('File', chunkBlob)
    formData.append('Index', index.toString())
    formData.append('UploadId', uploadId)
    formData.append('FileName', file.name)

    const controller = new AbortController()
    abortControllers.push(controller)

    uploadPart(formData, { signal: controller.signal })
      .then(() => {
        uploadedChunks++
        if (multipartForm.value.uploadType === 'file') {
          uploadProgress.value = Math.floor((uploadedChunks / chunkCount) * 100)
        } else {
          const fileProgress = (uploadedChunks / chunkCount) * (1 / totalFiles) * 100
          const folderProgress = (uploadedFiles / totalFiles) * 100
          uploadProgress.value = Math.floor(folderProgress + fileProgress)
        }
        resolve()
      })
      .catch((error) => {
        if (uploadStatus.value !== 'cancelled') {
          reject(new Error(`分片${index + 1}上传失败：${error.msg || error.message}`))
        } else {
          resolve()
        }
      })
  })
}

// 暂停/继续上传
const toggleUploadStatus = () => {
  if (uploadStatus.value === 'uploading') {
    abortControllers.forEach((controller) => controller.abort())
    uploadStatus.value = 'paused'
    ElMessage.info('上传已暂停，可点击“继续上传”恢复')
  } else if (uploadStatus.value === 'paused') {
    uploadStatus.value = 'uploading'
    if (multipartForm.value.uploadType === 'folder') {
      uploadNextFileInFolder()
    } else if (uploadQueue.length > 0) {
      handleSingleFileUpload(uploadQueue[0])
    }
  }
}

// 取消大文件上传
const cancelUpload = () => {
  abortControllers.forEach((controller) => controller.abort())
  uploadStatus.value = 'cancelled'
  uploadProgress.value = 0
  multipartFileList.value = []
  uploadQueue = []
  chunkCount = 0
  uploadedChunks = 0
  totalFiles = 0
  uploadedFiles = 0
  currentFileIndex = 0
  abortControllers = []
  multipartVisible.value = false
  formLoading.value = false
  ElMessage.info('已取消上传')
}

// 计算文件存储路径
const getFileStoragePath = (file) => {
  if (multipartForm.value.uploadType === 'folder') {
    return `${multipartForm.value.storagePath.replace(/\/$/, '')}/${file.name}`
  } else {
    return multipartForm.value.storagePath 
      ? `${multipartForm.value.storagePath.replace(/\/$/, '')}/${file.name}`
      : `/uploads/${file.name}`
  }
}

// 初始化
const init = async () => {
  try {
    // 加载字典
    const dictResponse = await getDicts([
      'sys_file_storage_type', 
      'sys_file_visibility', 
      'sys_file_status', 
      'sys_member_level'
    ])
    dictResponse.data.forEach((dict) => {
      state.options[dict.dictType] = dict.list.length ? dict.list : state.options[dict.dictType]
    })

    // 加载用户信息
    currentUserType.value = userInfo.value?.userType?.toString() || '2'
    currentUserMemberLevel.value = userInfo.value?.memberLevel?.toString() || '2'
console.log('state',state.options)
    // 初始加载文件列表
    handleQuery()
  } catch (error) {
    console.error('初始化失败：', error.message)
    ElMessage.warning('初始化失败，部分功能可能异常')
    loading.value = false
  }
}

// 生命周期挂载
onMounted(() => {
  init()
})

// 生命周期卸载：清理未完成的请求
onUnmounted(() => {
  abortControllers.forEach((controller) => controller.abort())
})
</script>

<style scoped>
.el-avatar {
  width: 32px;
  height: 32px;
  border-radius: 4px;
}
.mb8 {
  margin-bottom: 8px;
}
.el-divider--content-left {
  margin: 16px 0;
}

/* 编辑模式文件信息样式 */
.file-info-container {
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 16px;
  margin-bottom: 16px;
  background-color: #f9fafb;
}

.file-info-header {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
  gap: 12px;
}

.file-icon {
  font-size: 24px;
  color: #409eff;
}

.file-name {
  flex: 1;
  font-weight: 500;
  color: #303133;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.reupload-btn {
  color: #409eff;
}

.file-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-size: 13px;
}

.meta-item {
  display: flex;
  align-items: center;
  color: #606266;
}

.meta-label {
  font-weight: 500;
  margin-right: 4px;
  color: #909399;
}

/* 上传区域样式 */
.upload-demo {
  margin-bottom: 16px;
}
.el-upload__tip {
  margin-top: 8px;
  font-size: 12px;
}
.upload-controls {
  margin-top: 12px;
  display: flex;
  gap: 8px;
}

/* 下载进度样式 */
.download-progress {
  padding: 16px 0;
}
.download-info {
  margin-top: 12px;
  text-align: right;
  color: #606266;
  font-size: 12px;
}

/* 大文件上传表单样式 */
.multipart-form {
  margin-top: 10px;
}
.el-collapse {
  margin: 15px 0;
}
.el-upload__file-list {
  max-height: 200px;
  overflow-y: auto;
  margin-top: 10px;
}

/* 哈希文本样式 */
.hash-text {
  cursor: pointer;
  color: #409eff;
  text-decoration: underline;
}
.el-form-item__help{
  font-size: 10px;
}
</style>